package edu.umd.ion.wavemeter.client;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.logical.shared.BeforeSelectionEvent;
import com.google.gwt.event.logical.shared.BeforeSelectionHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.VerticalPanel;

import edu.umd.ion.wavemeter.service.CalibrationResult;
import edu.umd.ion.wavemeter.service.WavemeterData;
import edu.umd.ion.wavemeter.service.WavemeterServiceAsync;

/** Shows the tab with the calibration history.
 * @author pmaunz
 *
 */
public class CalibrationHistoryWidget extends Composite implements BeforeSelectionHandler<Integer> {
	private WavemeterServiceAsync WavemeterService;
	private HTML Message;
	private VerticalPanel Vertical;
	private Panel ErrorPanel;
	private Button Refresh;
	private HTML ErrorMessage;
	private UnitListBox Unit;
	private int LastAckSerialNumber;
	private int LastReportedSerialNumber;
	private HTML PopupMessage;
	private HorizontalPanel Popup;

	private native void reload() /*-{
    $wnd.location.reload();
   }-*/;


	private AsyncCallback<CalibrationResult[]> CalibrationHistoryCallback = 
			new AsyncCallback<CalibrationResult[]>() {
		public void onFailure(Throwable caught) {
			try {
				ErrorMessage.setHTML("Command: " + caught.getMessage());
				throw caught;
			} catch (IncompatibleRemoteServiceException e) {
				// this client is not compatible with the server; cleanup and refresh the 
				// browser
				reload();
			} catch (Throwable e) {
				// last resort -- a very unexpected exception
			}
		}

		public void onSuccess(CalibrationResult[] result) {
			ErrorMessage.setHTML("");
			showCalibrationHistory(result);
		}
	};
	
	public void showCalibrationHistory(CalibrationResult[] result) {
		if (result!=null) {
			if (Popup!=null && result.length>0) {
				CalibrationResult R = result[0];
				PopupMessage.setHTML(R.UserName + " calibrated the wavemeter at " + R.CalibrationDate.toString() + 
						" to channel " + R.Channel + " from " + Unit.convert(R.WavelengthBefore) + " to " + 
						Unit.convert(R.WavelengthAfter) );
				Popup.setVisible(LastReportedSerialNumber>LastAckSerialNumber);				
			}
			String MessageHTML = new String("<table border='1'><tr><td>Calibration Date</td><td>Channel</td>"+
					"<td>Old Wavelength</td><td>New Wavelength</td><td>Username</td><td>Hostname</td></tr>");
			for (int i=0; i<result.length; ++i) {
				CalibrationResult R = result[i];
				MessageHTML += "<tr><td>" + R.CalibrationDate.toString() + "</td><td>" + R.Channel + "</td><td>" 
				+ Unit.convert(R.WavelengthBefore) + "</td><td>" + Unit.convert(R.WavelengthAfter) + "</td><td>" 
				+ R.UserName + "</td><td>" + R.HostName + "</td></tr>";
			}
			MessageHTML += "</table>";
			Message.setHTML(MessageHTML);
		}
	}
	
	public void queryCalibrationHistory() {
			WavemeterService.calibrationHistory(CalibrationHistoryCallback);
	}
	
	public CalibrationHistoryWidget(WavemeterServiceAsync cb, Panel errorPanel, HorizontalPanel popup ) {
		WavemeterService = cb;
		ErrorPanel = errorPanel;
		Popup = popup;
		if (Popup!=null) {
			Popup.setStyleName("calibration-popup");
			PopupMessage = new HTML();
			Popup.add( new Button("Close", new ClickHandler() {
				@Override
				public void onClick(ClickEvent event) {
					LastAckSerialNumber = LastReportedSerialNumber;
					Popup.setVisible(false);					
				}
			}));
			Popup.add(PopupMessage);
		}
		
		HorizontalPanel Horiz = new HorizontalPanel();
		Refresh = new Button("Refresh",new ClickHandler() {
			public void onClick(ClickEvent event) {
				queryCalibrationHistory();
			}});
		Unit = new UnitListBox();
		Message = new HTML();
		
		ErrorMessage = new HTML();
		ErrorPanel.add(ErrorMessage);
		
		Horiz.add(Refresh);
		Horiz.add(Unit);
		Vertical = new VerticalPanel();
		Vertical.add(Horiz);
		Vertical.add(Message);
		initWidget(Vertical);
		queryCalibrationHistory();
	}

	@Override
	public void onBeforeSelection(BeforeSelectionEvent<Integer> event) {
		queryCalibrationHistory(); 
	}
	
	public void set(WavemeterData data) {
		LastReportedSerialNumber = data.CalibrationResultsSerial;
		if (LastAckSerialNumber==0) { LastAckSerialNumber=LastReportedSerialNumber; }
		if (LastReportedSerialNumber>LastAckSerialNumber ) {
			queryCalibrationHistory();
		}
	}
}
